cmake_minimum_required(VERSION 3.18)

# xxxxxxxxxxxxxxxxxxx 标准路径配置;vcpkg配置，必须位于project之前
include(cmake/mypath.cmake)
include(cmake/myvcpkg.cmake)

#================= 是否使用 thirdparty 中的库
# list(PREPEND CMAKE_PREFIX_PATH "${MY_THIRD_PARTY}")

#xxxxxxxxxxxxxxxxxxxxxxxxx 标出 cuda 是必须的
project(cuda_test LANGUAGES CXX CUDA)
# 检查 cuda
include(CheckLanguage)
check_language(CUDA)

#xxxxxxxxxxxxxxxxxxxxxxxxx common settings and functions
include(cmake/mycommon.cmake)
include(cmake/myfuns.cmake)

#xxxxxxxxxxxxxxxxxxxxxxxxx GPU 设置
# set(CMAKE_CUDA_ARCHITECTURES 120)
set(CMAKE_CUDA_ARCHITECTURES 86)
# if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
#   set(CMAKE_CUDA_ARCHITECTURES 86)
# endif()
message(STATUS "[ymy] CMAKE_CUDA_ARCHITECTURES => ${CMAKE_CUDA_ARCHITECTURES}")

# 针对NVCC编译器的特定设置
if(CMAKE_CUDA_COMPILER)
    message(STATUS "[ymy] CMAKE_CUDA_COMPILER => ${CMAKE_CUDA_COMPILER}")
    # 为NVCC添加特定编译选项
    # target_compile_options(${MY_EXE} PRIVATE
    #     $<$<COMPILE_LANGUAGE:CUDA>:--use_fast_math>
    #     # 其他NVCC选项...
    # )
endif()

#xxxxxxxxxxxxxxxxxxxxxxxxx find packages
include(cmake/myfind.cmake)

#xxxxxxxxxxxxxxxxxxxxxxxxx  添加 target
set(MY_EXE ${PROJECT_NAME})
include_directories(${MY_ROOT_DIR}/include)

#======================== 收集所有源文件
# 头文件（.h / .cuh）
file(GLOB_RECURSE MY_HDR_FILES CONFIGURE_DEPENDS
    "include/*.h"
    "include/*.cuh"
    "src/*.h"
    "src/*.cuh"
    )

# CUDA 源文件
file(GLOB_RECURSE MY_CU_FILES CONFIGURE_DEPENDS "src/*.cu")
# C++ 源文件
file(GLOB_RECURSE MY_CPP_FILES CONFIGURE_DEPENDS "src/*.cpp" "src/*.cxx")
message(STATUS "[ymy] MY_HDR_FILES => ${MY_HDR_FILES}")
message(STATUS "[ymy] MY_CU_FILES => ${MY_CU_FILES}")
message(STATUS "[ymy] MY_CPP_FILES => ${MY_CPP_FILES}")

# 告诉 VS 哪些文件是“仅头文件”
set_source_files_properties(${MY_HDR_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
# 虚拟目录分组
source_group(TREE "${MY_ROOT_DIR}" FILES ${MY_HDR_FILES})
source_group(TREE "${MY_ROOT_DIR}" FILES ${MY_CU_FILES} ${MY_CPP_FILES})
# source_group("Header Files" FILES ${MY_HDR_FILES})
# source_group("Source Files" FILES ${MY_CU_FILES} ${MY_CPP_FILES})

# 添加可执行文件，将CUDA文件单独列出
add_executable(${MY_EXE}
    ${MY_CU_FILES} ${MY_CPP_FILES} ${MY_HDR_FILES}
    )
# 添加宏定义，确保spdlog正确使用fmt
# target_compile_definitions(${MY_EXE} PRIVATE
    # SPDLOG_HEADER_ONLY
    # SPDLOG_FMT_EXTERNAL
    # FMT_HEADER_ONLY=1
# )

#============================= 链接CUDA库
target_link_libraries(${MY_EXE}
    PRIVATE cudart
    PRIVATE spdlog::spdlog
    PRIVATE fmt::fmt
)

#============================= transform RelWithDebInfo -> Debug 配置
my_config_msvc_relwithdebinfo(${MY_EXE})


# 为CUDA文件设置正确的编译特性
# target_compile_features(${MY_EXE} PRIVATE cxx_std_17)
# 确保CUDA文件使用CUDA编译器而不是C++编译器
# set_source_files_properties(${MY_CU_FILES} PROPERTIES LANGUAGE CUDA)
# 设置CUDA文件的包含目录
# include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRS})

# 为CUDA文件设置特定的编译选项
# set_property(TARGET ${MY_EXE} PROPERTY CUDA_ARCHITECTURES ${CMAKE_CUDA_ARCHITECTURES})

# 为CUDA文件添加特定宏定义
# set_property(TARGET ${MY_EXE} PROPERTY CUDA_SEPARABLE_COMPILATION ON)
# set_property(TARGET ${MY_EXE} PROPERTY CUDA_RESOLVE_DEVICE_SYMBOLS ON)

#------------ 在顶层 CMakeLists.txt 文件中设置默认启动项目
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${MY_EXE})

# =============================== copy dlls
my_cp_dlls(${MY_EXE})
# my_cp_cuda_dlls(${MY_EXE})

#xxxxxxxxxxxxxxxxxxxxxxxxx 添加 CMake 测试
enable_testing()
add_test(NAME cuda_device_info_test COMMAND ${MY_EXE})